import { Checkbox } from 'antd'
import { isEmpty } from 'lodash-es'
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'

import AekTree from '@/components/AekTree'

const TREE_KEY = 'menuId'
const TREE_TITLE = 'menuName'

/** 将权限树转成权限列表 */
const getAllPermissionList = treeData => {
  const allPermissionList = []
  // 递归遍历树，获取所有选中的节点的权限列表
  const loop = list => {
    list.forEach(item => {
      if (item.children?.length) {
        loop(item.children)
      }
      if (!item.permissionList) return
      allPermissionList.push(...item.permissionList)
    })
  }
  loop(treeData)
  return allPermissionList
}

/**
 * 将菜单树转成菜单列表
 * @param {Array} treeData 完整数据
 * @param {Array} checkedTreeData 选中的数据
 * @returns
 */
const getCheckedKeys = (treeData, checkedTreeData) => {
  const allCheckedKeys = []
  const checkedKeys = []
  // 递归遍历树，获取所有选中的节点的权限列表
  const loopGetCheckedKeys = list => {
    list.forEach(item => {
      allCheckedKeys.push(item[TREE_KEY])
      if (item.children?.length) {
        loopGetCheckedKeys(item.children)
      }
    })
  }
  loopGetCheckedKeys(checkedTreeData)

  // 递归遍历树，判断当前节点的子节点是否全部存在
  const loopCheckChildrenAllChecked = list => {
    list.forEach(item => {
      if (item.children?.length) {
        loopCheckChildrenAllChecked(item.children)
      }
      if (
        (isEmpty(item.children) && allCheckedKeys.includes(item[TREE_KEY])) ||
        (!isEmpty(item.children) && item.children.every(child => checkedKeys.includes(child[TREE_KEY])))
      ) {
        checkedKeys.push(item[TREE_KEY])
      }
    })
  }
  loopCheckChildrenAllChecked(treeData)
  return { allCheckedKeys, checkedKeys }
}

const MenuTree = forwardRef(({ treeData, checkedTreeData }, ref) => {
  /** @type {Array} 所有选中的节点,包含半选 */
  const [allCheckedKeys, setAllCheckedKeys] = useState([])
  /** @type {Array} 所有选中的节点，不包含半选 */
  const [checkedKeys, setCheckedKeys] = useState([])
  const [permissionCheckedKeys, setPermissionCheckedKeys] = useState([])

  useEffect(() => {
    const { allCheckedKeys, checkedKeys } = getCheckedKeys(treeData, checkedTreeData)
    const allCheckedPermissionList = getAllPermissionList(checkedTreeData)

    setAllCheckedKeys(allCheckedKeys)
    setCheckedKeys(checkedKeys)
    setPermissionCheckedKeys(allCheckedPermissionList.map(item => item[TREE_KEY]))
  }, [])

  const getAllCheckedKeys = () => {
    return {
      allCheckedKeys,
      permissionCheckedKeys,
    }
  }

  useImperativeHandle(ref, () => ({
    getAllCheckedKeys,
  }))

  return (
    <div style={{ height: 'calc(100vh - 240px)' }}>
      <AekTree
        {...{
          treeData,
          fieldNames: { key: TREE_KEY, title: TREE_TITLE },
          checkable: true,
          checkedKeys,
          titleRender: node => {
            if (!node.permissionList) return node[TREE_TITLE]
            return (
              <div className='flex'>
                <div className='flex flex-none items-center'>{node[TREE_TITLE]}</div>
                <div className='ml30px'>
                  {node.permissionList.map(permission => (
                    <Checkbox
                      key={permission[TREE_KEY]}
                      disabled={!checkedKeys.includes(node[TREE_KEY])}
                      checked={permissionCheckedKeys.includes(permission[TREE_KEY])}
                      onChange={e => {
                        e.target.checked
                          ? setPermissionCheckedKeys([...permissionCheckedKeys, permission[TREE_KEY]])
                          : setPermissionCheckedKeys(
                              permissionCheckedKeys.filter(menuId => menuId !== permission[TREE_KEY]),
                            )
                      }}
                    >
                      {permission[TREE_TITLE]}
                    </Checkbox>
                  ))}
                </div>
              </div>
            )
          },
          onCheck: (checkedKeys, info) => {
            const { checked, halfCheckedKeys, node } = info
            setCheckedKeys(checkedKeys)
            setAllCheckedKeys([...halfCheckedKeys, ...checkedKeys])

            const allPermissionList = getAllPermissionList([node])

            if (checked) {
              setPermissionCheckedKeys([
                ...permissionCheckedKeys,
                ...allPermissionList.map(permission => permission[TREE_KEY]),
              ])
            } else {
              setPermissionCheckedKeys(
                permissionCheckedKeys.filter(
                  menuId => !allPermissionList?.find(permission => permission[TREE_KEY] === menuId),
                ),
              )
            }
          },
        }}
      />
    </div>
  )
})

export default MenuTree
